From 9aeab194c243007b888c2d3a3b9c6ac7bcf35f91 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 18 May 2005 13:12:57 +0000 Subject: [PATCH] bitkeeper revision 1.1443 (428b3f59xxbCVcbUBrHu1R1TkWcYhg) Cleaner GDT interface. Xen now reserves the last 2 pages of a full-size (16 page) GDT. A guest can register a GDT with up to 7k entries. Xen automatically makes the GDT up to max size with empty page mappings, and turns page faults in that area to #GP(selector). Signed-off-by: Keir Fraser --- .rootkeys | 1 - .../i386-xen/i386-xen/machdep.c | 8 +- .../i386-xen/i386-xen/mp_machdep.c | 2 +- .../arch/xen/i386/kernel/smpboot.c | 3 - .../include/asm-xen/asm-i386/segment.h | 4 +- .../include/asm-xen/asm-x86_64/segment.h | 2 +- .../sys/arch/xen/i386/machdep.c | 4 +- tools/libxc/xc_linux_restore.c | 7 -- xen/arch/x86/boot/x86_32.S | 34 ++--- xen/arch/x86/boot/x86_64.S | 75 ++++++----- xen/arch/x86/dom0_ops.c | 10 -- xen/arch/x86/domain.c | 108 ++++++++-------- xen/arch/x86/domain_build.c | 3 - xen/arch/x86/mm.c | 63 ++-------- xen/arch/x86/setup.c | 24 ++-- xen/arch/x86/trampoline.S | 7 +- xen/arch/x86/traps.c | 117 ++++++++++++------ xen/arch/x86/x86_32/seg_fixup.c | 14 +-- xen/arch/x86/x86_32/traps.c | 5 +- xen/include/asm-x86/config.h | 28 ++--- xen/include/asm-x86/desc.h | 23 +++- xen/include/asm-x86/domain.h | 2 - xen/include/asm-x86/ldt.h | 2 +- xen/include/asm-x86/mm.h | 3 - xen/include/asm-x86/processor.h | 9 -- xen/include/asm-x86/x86_64/ldt.h | 39 ------ xen/include/public/arch-x86_32.h | 28 ++--- xen/include/public/arch-x86_64.h | 25 ++-- 28 files changed, 292 insertions(+), 358 deletions(-) delete mode 100644 xen/include/asm-x86/x86_64/ldt.h diff --git a/.rootkeys b/.rootkeys index 797542a380..6a7a851ef8 100644 --- a/.rootkeys +++ b/.rootkeys @@ -1426,7 +1426,6 @@ 41bf1717bML6GxpclTWJabiaO5W5vg xen/include/asm-x86/x86_64/asm_defns.h 404f1b9ceJeGVaPNIENm2FkK0AgEOQ xen/include/asm-x86/x86_64/current.h 41febc4b1aCGLsm0Y0b_82h7lFtrEA xen/include/asm-x86/x86_64/domain_page.h -404f1badfXZJZ2sU8sh9PS2EZvd19Q xen/include/asm-x86/x86_64/ldt.h 4208e2a3Fktw4ZttKdDxbhvTQ6brfQ xen/include/asm-x86/x86_64/page.h 404f1bb86rAXB3aLS1vYdcqpJiEcyg xen/include/asm-x86/x86_64/regs.h 40e1966azOJZfNI6Ilthe6Q-T3Hewg xen/include/asm-x86/x86_64/string.h diff --git a/freebsd-5.3-xen-sparse/i386-xen/i386-xen/machdep.c b/freebsd-5.3-xen-sparse/i386-xen/i386-xen/machdep.c index efda2eac13..3bdfd7a4b4 100644 --- a/freebsd-5.3-xen-sparse/i386-xen/i386-xen/machdep.c +++ b/freebsd-5.3-xen-sparse/i386-xen/i386-xen/machdep.c @@ -1599,11 +1599,7 @@ init386(void) gdt_segs[GDATA_SEL].ssd_limit = atop(0 - ((1 << 26) - (1 << 22) + (1 << 16))); #endif #ifdef SMP - /* XXX this will blow up if there are more than 512/NGDT vcpus - will never - * be an issue in the real world but should add an assert on general principles - * we'll likely blow up when we hit LAST_RESERVED_GDT_ENTRY, at which point we - * would need to start allocating more pages for the GDT - */ + /* XXX this will blow up if there are more than 512/NGDT vcpus */ pc = &SMP_prvspace[0].pcpu; for (i = 0; i < ncpus; i++) { cpu_add(i, (i == 0)); @@ -1633,7 +1629,7 @@ init386(void) PT_SET_MA(gdt, *vtopte((unsigned long)gdt) & ~PG_RW); gdtmachpfn = vtomach(gdt) >> PAGE_SHIFT; - PANIC_IF(HYPERVISOR_set_gdt(&gdtmachpfn, LAST_RESERVED_GDT_ENTRY + 1) != 0); + PANIC_IF(HYPERVISOR_set_gdt(&gdtmachpfn, 512) != 0); lgdt_finish(); diff --git a/freebsd-5.3-xen-sparse/i386-xen/i386-xen/mp_machdep.c b/freebsd-5.3-xen-sparse/i386-xen/i386-xen/mp_machdep.c index 5ef412ac21..d084a54303 100644 --- a/freebsd-5.3-xen-sparse/i386-xen/i386-xen/mp_machdep.c +++ b/freebsd-5.3-xen-sparse/i386-xen/i386-xen/mp_machdep.c @@ -533,7 +533,7 @@ init_secondary(void) myid = bootAP; gdtmachpfn = vtomach(gdt) >> PAGE_SHIFT; - PANIC_IF(HYPERVISOR_set_gdt(&gdtmachpfn, LAST_RESERVED_GDT_ENTRY + 1) != 0); + PANIC_IF(HYPERVISOR_set_gdt(&gdtmachpfn, 512) != 0); lgdt_finish(); diff --git a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c index 9a158e2900..a716095376 100644 --- a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c +++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c @@ -856,9 +856,6 @@ static int __init do_boot_cpu(int apicid) cpu_gdt_descr[cpu].size = cpu_gdt_descr[0].size; memcpy((void *)cpu_gdt_descr[cpu].address, (void *)cpu_gdt_descr[0].address, cpu_gdt_descr[0].size); - memset((char *)cpu_gdt_descr[cpu].address + - FIRST_RESERVED_GDT_ENTRY * 8, 0, - NR_RESERVED_GDT_ENTRIES * 8); memset(&ctxt, 0, sizeof(ctxt)); diff --git a/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/segment.h b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/segment.h index a9657fbe74..5496d69023 100644 --- a/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/segment.h +++ b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/segment.h @@ -74,9 +74,9 @@ #define GDT_ENTRY_DOUBLEFAULT_TSS 31 /* - * The GDT has LAST_RESERVED_GDT_ENTRY + 1 entries + * The GDT has 32 entries */ -#define GDT_ENTRIES (LAST_RESERVED_GDT_ENTRY + 1) +#define GDT_ENTRIES 32 #define GDT_SIZE (GDT_ENTRIES * 8) diff --git a/linux-2.6.11-xen-sparse/include/asm-xen/asm-x86_64/segment.h b/linux-2.6.11-xen-sparse/include/asm-xen/asm-x86_64/segment.h index 586469716f..db5926a999 100644 --- a/linux-2.6.11-xen-sparse/include/asm-xen/asm-x86_64/segment.h +++ b/linux-2.6.11-xen-sparse/include/asm-xen/asm-x86_64/segment.h @@ -40,7 +40,7 @@ #define FS_TLS_SEL ((GDT_ENTRY_TLS_MIN+FS_TLS)*8 + 3) #define IDT_ENTRIES 256 -#define GDT_ENTRIES (LAST_RESERVED_GDT_ENTRY + 1) +#define GDT_ENTRIES 16 #define GDT_SIZE (GDT_ENTRIES * 8) #define TLS_SIZE (GDT_ENTRY_TLS_ENTRIES * 8) diff --git a/netbsd-2.0-xen-sparse/sys/arch/xen/i386/machdep.c b/netbsd-2.0-xen-sparse/sys/arch/xen/i386/machdep.c index 54752025b6..54cf3fa619 100644 --- a/netbsd-2.0-xen-sparse/sys/arch/xen/i386/machdep.c +++ b/netbsd-2.0-xen-sparse/sys/arch/xen/i386/machdep.c @@ -1430,8 +1430,8 @@ initgdt() pmap_kenter_pa((vaddr_t)gdt, (uint32_t)gdt - KERNBASE, VM_PROT_READ); XENPRINTK(("loading gdt %lx, %d entries\n", frames[0] << PAGE_SHIFT, - LAST_RESERVED_GDT_ENTRY + 1)); - if (HYPERVISOR_set_gdt(frames, LAST_RESERVED_GDT_ENTRY + 1)) + NGDT); + if (HYPERVISOR_set_gdt(frames, NGDT)) panic("HYPERVISOR_set_gdt failed!\n"); lgdt_finish(); #endif diff --git a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c index 0d05d0f903..d50d738439 100644 --- a/tools/libxc/xc_linux_restore.c +++ b/tools/libxc/xc_linux_restore.c @@ -535,13 +535,6 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) ctxt.gdt_frames[i] = pfn_to_mfn_table[pfn]; } - /* Zero hypervisor GDT entries (supresses ugly warning) */ - p_gdt = xc_map_foreign_range( - xc_handle, dom, PAGE_SIZE, PROT_WRITE, ctxt.gdt_frames[0]); - memset( p_gdt + FIRST_RESERVED_GDT_ENTRY*8, 0, - NR_RESERVED_GDT_ENTRIES*8 ); - munmap( p_gdt, PAGE_SIZE ); - /* Uncanonicalise the page table base pointer. */ pfn = ctxt.pt_base >> PAGE_SHIFT; if ( (pfn >= nr_pfns) || ((pfn_type[pfn]<ABTYPE_MASK) != L2TAB) ) diff --git a/xen/arch/x86/boot/x86_32.S b/xen/arch/x86/boot/x86_32.S index 49d6e34bb3..74edbe1ebf 100644 --- a/xen/arch/x86/boot/x86_32.S +++ b/xen/arch/x86/boot/x86_32.S @@ -1,5 +1,6 @@ #include #include +#include #include #define SECONDARY_CPU_FLAG 0xA5A5A5A5 @@ -181,40 +182,39 @@ ENTRY(stack_start) .word 0 idt_descr: - .word 256*8-1 + .word 256*8-1 idt: .long idt_table .word 0 gdt_descr: - .word (LAST_RESERVED_GDT_ENTRY*8)+7 -gdt: - .long gdt_table /* gdt base */ + .word LAST_RESERVED_GDT_BYTE +gdt: + .long gdt_table - FIRST_RESERVED_GDT_BYTE .word 0 nopaging_gdt_descr: - .word (LAST_RESERVED_GDT_ENTRY*8)+7 - .long gdt_table-__PAGE_OFFSET + .word LAST_RESERVED_GDT_BYTE + .long gdt_table - FIRST_RESERVED_GDT_BYTE - __PAGE_OFFSET - ALIGN + .org 0x1000 /* NB. Rings != 0 get access up to 0xFC400000. This allows access to the */ /* machine->physical mapping table. Ring 0 can access all memory. */ ENTRY(gdt_table) - .fill FIRST_RESERVED_GDT_ENTRY,8,0 .quad 0x0000000000000000 /* unused */ - .quad 0x00cf9a000000ffff /* 0x0808 ring 0 4.00GB code at 0x0 */ - .quad 0x00cf92000000ffff /* 0x0810 ring 0 4.00GB data at 0x0 */ - .quad 0x00cfba000000c3ff /* 0x0819 ring 1 3.95GB code at 0x0 */ - .quad 0x00cfb2000000c3ff /* 0x0821 ring 1 3.95GB data at 0x0 */ - .quad 0x00cffa000000c3ff /* 0x082b ring 3 3.95GB code at 0x0 */ - .quad 0x00cff2000000c3ff /* 0x0833 ring 3 3.95GB data at 0x0 */ + .quad 0x00cf9a000000ffff /* 0xe008 ring 0 4.00GB code at 0x0 */ + .quad 0x00cf92000000ffff /* 0xe010 ring 0 4.00GB data at 0x0 */ + .quad 0x00cfba000000c3ff /* 0xe019 ring 1 3.95GB code at 0x0 */ + .quad 0x00cfb2000000c3ff /* 0xe021 ring 1 3.95GB data at 0x0 */ + .quad 0x00cffa000000c3ff /* 0xe02b ring 3 3.95GB code at 0x0 */ + .quad 0x00cff2000000c3ff /* 0xe033 ring 3 3.95GB data at 0x0 */ .quad 0x0000000000000000 /* unused */ .fill 2*NR_CPUS,8,0 /* space for TSS and LDT per CPU */ - .org 0x1000 -ENTRY(idle_pg_table) # Initial page directory is 4kB .org 0x2000 +ENTRY(idle_pg_table) # Initial page directory is 4kB + .org 0x3000 ENTRY(cpu0_stack) - .org 0x2000 + STACK_SIZE + .org 0x3000 + STACK_SIZE ENTRY(stext) ENTRY(_stext) diff --git a/xen/arch/x86/boot/x86_64.S b/xen/arch/x86/boot/x86_64.S index 26193cb86e..56b2dcb5e5 100644 --- a/xen/arch/x86/boot/x86_64.S +++ b/xen/arch/x86/boot/x86_64.S @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -51,7 +52,7 @@ __start: cli /* Set up a few descriptors: on entry only CS is guaranteed good. */ - lgdt %cs:0x1001f0 + lgdt %cs:0x100400 mov $(__HYPERVISOR_DS32),%ecx mov %ecx,%ds mov %ecx,%es @@ -64,7 +65,7 @@ __start: jne not_multiboot /* Save the Multiboot info structure for later use. */ - mov %ebx,0x1001e0 + mov %ebx,0x100300 /* We begin by interrogating the CPU for the presence of long mode. */ mov $0x80000000,%eax @@ -167,44 +168,40 @@ __high_start: loop 1b /* Pass off the Multiboot info structure to C land. */ - mov 0x1001e0,%edi + mov 0x100300,%edi lea start(%rip),%rax sub $0x100000,%rax add %rax,%rdi call __start_xen ud2 /* Force a panic (invalid opcode). */ +/* This is the default interrupt handler. */ +int_msg: + .asciz "Unknown interrupt\n" +ignore_int: + cld + leaq int_msg(%rip),%rdi + call printf +1: jmp 1b + .code32 - .org 0x1e0 + .org 0x300 /*** DESCRIPTOR TABLES ***/ .globl idt -.globl gdt +.globl gdt - .org 0x1f0 - .word (LAST_RESERVED_GDT_ENTRY*8)+7 - .long 0x100200 # gdt_table + .org 0x400 + .word LAST_RESERVED_GDT_BYTE + .long 0x101000 - FIRST_RESERVED_GDT_BYTE - .org 0x200 -ENTRY(gdt_table) - .fill FIRST_RESERVED_GDT_ENTRY,8,0 - .quad 0x0000000000000000 /* unused */ - .quad 0x00cf9a000000ffff /* 0x0808 ring 0 code, compatibility */ - .quad 0x00af9a000000ffff /* 0x0810 ring 0 code, 64-bit mode */ - .quad 0x00cf92000000ffff /* 0x0818 ring 0 data */ - .quad 0x00cffa000000ffff /* 0x0823 ring 3 code, compatibility */ - .quad 0x00cff2000000ffff /* 0x082b ring 3 data */ - .quad 0x00affa000000ffff /* 0x0833 ring 3 code, 64-bit mode */ - .quad 0x0000000000000000 /* unused */ - .fill 4*NR_CPUS,8,0 /* space for TSS and LDT per CPU */ - .word 0 gdt_descr: - .word (LAST_RESERVED_GDT_ENTRY*8)+7 + .word LAST_RESERVED_GDT_BYTE gdt: - .quad gdt_table + .quad gdt_table - FIRST_RESERVED_GDT_BYTE .word 0 idt_descr: @@ -218,8 +215,20 @@ ENTRY(stack_start) high_start: .quad __high_start + .org 0x1000 +ENTRY(gdt_table) + .quad 0x0000000000000000 /* unused */ + .quad 0x00cf9a000000ffff /* 0xe008 ring 0 code, compatibility */ + .quad 0x00af9a000000ffff /* 0xe010 ring 0 code, 64-bit mode */ + .quad 0x00cf92000000ffff /* 0xe018 ring 0 data */ + .quad 0x00cffa000000ffff /* 0xe023 ring 3 code, compatibility */ + .quad 0x00cff2000000ffff /* 0xe02b ring 3 data */ + .quad 0x00affa000000ffff /* 0xe033 ring 3 code, 64-bit mode */ + .quad 0x0000000000000000 /* unused */ + .fill 4*NR_CPUS,8,0 /* space for TSS and LDT per CPU */ + /* Initial PML4 -- level-4 page table */ - .org 0x1000 + .org 0x2000 ENTRY(idle_pg_table) ENTRY(idle_pg_table_4) .quad 0x0000000000102007 # PML4[0] @@ -227,12 +236,12 @@ ENTRY(idle_pg_table_4) .quad 0x0000000000102007 # PML4[262] /* Initial PDP -- level-3 page table */ - .org 0x2000 + .org 0x3000 ENTRY(idle_pg_table_l3) .quad 0x0000000000103007 /* Initial PDE -- level-2 page table. */ - .org 0x3000 + .org 0x4000 ENTRY(idle_pg_table_l2) .macro identmap from=0, count=512 .if \count-1 @@ -244,20 +253,10 @@ ENTRY(idle_pg_table_l2) .endm identmap /* Too orangey for crows :-) */ - .org 0x4000 + .org 0x5000 ENTRY(cpu0_stack) - .org 0x4000 + STACK_SIZE + .org 0x5000 + STACK_SIZE .code64 ENTRY(stext) ENTRY(_stext) - -/* This is the default interrupt handler. */ -int_msg: - .asciz "Unknown interrupt\n" -ignore_int: - cld - leaq int_msg(%rip),%rdi - call printf -1: jmp 1b - diff --git a/xen/arch/x86/dom0_ops.c b/xen/arch/x86/dom0_ops.c index fb4bd53338..85fbe494f1 100644 --- a/xen/arch/x86/dom0_ops.c +++ b/xen/arch/x86/dom0_ops.c @@ -376,7 +376,6 @@ long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op) void arch_getdomaininfo_ctxt( struct exec_domain *ed, struct vcpu_guest_context *c) { - int i; #ifdef __i386__ /* Remove when x86_64 VMX is implemented */ #ifdef CONFIG_VMX extern void save_vmx_cpu_user_regs(struct cpu_user_regs *); @@ -406,15 +405,6 @@ void arch_getdomaininfo_ctxt( c->flags |= VGCF_VMX_GUEST; #endif - c->gdt_ents = 0; - if ( GET_GDT_ADDRESS(ed) == GDT_VIRT_START(ed) ) - { - for ( i = 0; i < 16; i++ ) - c->gdt_frames[i] = - l1e_get_pfn(ed->arch.perdomain_ptes[i]); - c->gdt_ents = GET_GDT_ENTRIES(ed); - } - c->pt_base = pagetable_val(ed->arch.guest_table); c->vm_assist = ed->domain->vm_assist; diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index e99f4f4743..0b93ed87a2 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -244,57 +244,66 @@ void arch_do_createdomain(struct exec_domain *ed) ed->arch.flags = TF_kernel_mode; - if ( d->domain_id != IDLE_DOMAIN_ID ) - { - ed->arch.schedule_tail = continue_nonidle_task; - - d->shared_info = (void *)alloc_xenheap_page(); - memset(d->shared_info, 0, PAGE_SIZE); - ed->vcpu_info = &d->shared_info->vcpu_data[ed->vcpu_id]; - ed->cpumap = CPUMAP_RUNANYWHERE; - SHARE_PFN_WITH_DOMAIN(virt_to_page(d->shared_info), d); - machine_to_phys_mapping[virt_to_phys(d->shared_info) >> - PAGE_SHIFT] = INVALID_M2P_ENTRY; - - d->arch.mm_perdomain_pt = (l1_pgentry_t *)alloc_xenheap_page(); - memset(d->arch.mm_perdomain_pt, 0, PAGE_SIZE); - machine_to_phys_mapping[virt_to_phys(d->arch.mm_perdomain_pt) >> - PAGE_SHIFT] = INVALID_M2P_ENTRY; - ed->arch.perdomain_ptes = d->arch.mm_perdomain_pt; + if ( d->domain_id == IDLE_DOMAIN_ID ) + return; - ed->arch.guest_vtable = __linear_l2_table; - ed->arch.shadow_vtable = __shadow_linear_l2_table; + ed->arch.schedule_tail = continue_nonidle_task; + + d->shared_info = (void *)alloc_xenheap_page(); + memset(d->shared_info, 0, PAGE_SIZE); + ed->vcpu_info = &d->shared_info->vcpu_data[ed->vcpu_id]; + ed->cpumap = CPUMAP_RUNANYWHERE; + SHARE_PFN_WITH_DOMAIN(virt_to_page(d->shared_info), d); + machine_to_phys_mapping[virt_to_phys(d->shared_info) >> + PAGE_SHIFT] = INVALID_M2P_ENTRY; + + d->arch.mm_perdomain_pt = (l1_pgentry_t *)alloc_xenheap_page(); + memset(d->arch.mm_perdomain_pt, 0, PAGE_SIZE); + machine_to_phys_mapping[virt_to_phys(d->arch.mm_perdomain_pt) >> + PAGE_SHIFT] = INVALID_M2P_ENTRY; + ed->arch.perdomain_ptes = d->arch.mm_perdomain_pt; + ed->arch.perdomain_ptes[FIRST_RESERVED_GDT_PAGE] = + l1e_create_pfn(page_to_pfn(virt_to_page(gdt_table)), + __PAGE_HYPERVISOR); + + ed->arch.guest_vtable = __linear_l2_table; + ed->arch.shadow_vtable = __shadow_linear_l2_table; #ifdef __x86_64__ - ed->arch.guest_vl3table = __linear_l3_table; - ed->arch.guest_vl4table = __linear_l4_table; - - d->arch.mm_perdomain_l2 = (l2_pgentry_t *)alloc_xenheap_page(); - memset(d->arch.mm_perdomain_l2, 0, PAGE_SIZE); - d->arch.mm_perdomain_l2[l2_table_offset(PERDOMAIN_VIRT_START)] = - l2e_create_phys(__pa(d->arch.mm_perdomain_pt), - __PAGE_HYPERVISOR); - d->arch.mm_perdomain_l3 = (l3_pgentry_t *)alloc_xenheap_page(); - memset(d->arch.mm_perdomain_l3, 0, PAGE_SIZE); - d->arch.mm_perdomain_l3[l3_table_offset(PERDOMAIN_VIRT_START)] = - l3e_create_phys(__pa(d->arch.mm_perdomain_l2), + ed->arch.guest_vl3table = __linear_l3_table; + ed->arch.guest_vl4table = __linear_l4_table; + + d->arch.mm_perdomain_l2 = (l2_pgentry_t *)alloc_xenheap_page(); + memset(d->arch.mm_perdomain_l2, 0, PAGE_SIZE); + d->arch.mm_perdomain_l2[l2_table_offset(PERDOMAIN_VIRT_START)] = + l2e_create_phys(__pa(d->arch.mm_perdomain_pt), + __PAGE_HYPERVISOR); + d->arch.mm_perdomain_l3 = (l3_pgentry_t *)alloc_xenheap_page(); + memset(d->arch.mm_perdomain_l3, 0, PAGE_SIZE); + d->arch.mm_perdomain_l3[l3_table_offset(PERDOMAIN_VIRT_START)] = + l3e_create_phys(__pa(d->arch.mm_perdomain_l2), __PAGE_HYPERVISOR); #endif - - (void)ptwr_init(d); - - shadow_lock_init(d); - INIT_LIST_HEAD(&d->arch.free_shadow_frames); - } + + (void)ptwr_init(d); + + shadow_lock_init(d); + INIT_LIST_HEAD(&d->arch.free_shadow_frames); } void arch_do_boot_vcpu(struct exec_domain *ed) { struct domain *d = ed->domain; + + ed->arch.flags = TF_kernel_mode; + ed->arch.schedule_tail = d->exec_domain[0]->arch.schedule_tail; - ed->arch.perdomain_ptes = + + ed->arch.perdomain_ptes = d->arch.mm_perdomain_pt + (ed->vcpu_id << PDPT_VCPU_SHIFT); - ed->arch.flags = TF_kernel_mode; + ed->arch.perdomain_ptes[FIRST_RESERVED_GDT_PAGE] = + l1e_create_pfn(page_to_pfn(virt_to_page(gdt_table)), + __PAGE_HYPERVISOR); } #ifdef CONFIG_VMX @@ -444,16 +453,10 @@ int arch_set_info_guest( return -EINVAL; } - /* Failure to set GDT is harmless. */ - SET_GDT_ENTRIES(ed, DEFAULT_GDT_ENTRIES); - SET_GDT_ADDRESS(ed, DEFAULT_GDT_ADDRESS); - if ( c->gdt_ents != 0 ) + if ( (rc = (int)set_gdt(ed, c->gdt_frames, c->gdt_ents)) != 0 ) { - if ( (rc = (int)set_gdt(ed, c->gdt_frames, c->gdt_ents)) != 0 ) - { - put_page_and_type(&frame_table[phys_basetab>>PAGE_SHIFT]); - return rc; - } + put_page_and_type(&frame_table[phys_basetab>>PAGE_SHIFT]); + return rc; } #ifdef CONFIG_VMX @@ -754,7 +757,14 @@ static void __context_switch(void) set_bit(cpu, &n->domain->cpuset); write_ptbase(n); - __asm__ __volatile__ ( "lgdt %0" : "=m" (*n->arch.gdt) ); + + if ( p->vcpu_id != n->vcpu_id ) + { + char gdt_load[10]; + *(unsigned short *)(&gdt_load[0]) = LAST_RESERVED_GDT_BYTE; + *(unsigned long *)(&gdt_load[2]) = GDT_VIRT_START(n); + __asm__ __volatile__ ( "lgdt %0" : "=m" (gdt_load) ); + } if ( p->domain != n->domain ) clear_bit(cpu, &p->domain->cpuset); diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c index 560cea0a99..72ded37bdc 100644 --- a/xen/arch/x86/domain_build.c +++ b/xen/arch/x86/domain_build.c @@ -225,9 +225,6 @@ int construct_dom0(struct domain *d, mpt_alloc = (vpt_start - dsi.v_start) + alloc_start; - SET_GDT_ENTRIES(ed, DEFAULT_GDT_ENTRIES); - SET_GDT_ADDRESS(ed, DEFAULT_GDT_ADDRESS); - /* * We're basically forcing default RPLs to 1, so that our "what privilege * level are we returning to?" logic works. diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index afbdeaa81d..ccf8e3725a 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -2244,11 +2244,13 @@ void destroy_gdt(struct exec_domain *ed) int i; unsigned long pfn; - for ( i = 0; i < 16; i++ ) + ed->arch.guest_context.gdt_ents = 0; + for ( i = 0; i < FIRST_RESERVED_GDT_PAGE; i++ ) { if ( (pfn = l1e_get_pfn(ed->arch.perdomain_ptes[i])) != 0 ) put_page_and_type(&frame_table[pfn]); ed->arch.perdomain_ptes[i] = l1e_empty(); + ed->arch.guest_context.gdt_frames[i] = 0; } } @@ -2259,56 +2261,31 @@ long set_gdt(struct exec_domain *ed, { struct domain *d = ed->domain; /* NB. There are 512 8-byte entries per GDT page. */ - int i = 0, nr_pages = (entries + 511) / 512; - struct desc_struct *vgdt; + int i, nr_pages = (entries + 511) / 512; unsigned long pfn; - /* Check the first page in the new GDT. */ - if ( (pfn = frames[0]) >= max_page ) - goto fail; - + if ( entries > FIRST_RESERVED_GDT_ENTRY ) + return -EINVAL; + shadow_sync_all(d); - /* The first page is special because Xen owns a range of entries in it. */ - if ( !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) ) - { - /* GDT checks failed: try zapping the Xen reserved entries. */ - if ( !get_page_and_type(&frame_table[pfn], d, PGT_writable_page) ) - goto fail; - vgdt = map_domain_mem(pfn << PAGE_SHIFT); - memset(vgdt + FIRST_RESERVED_GDT_ENTRY, 0, - NR_RESERVED_GDT_ENTRIES*8); - unmap_domain_mem(vgdt); - put_page_and_type(&frame_table[pfn]); - - /* Okay, we zapped the entries. Now try the GDT checks again. */ - if ( !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) ) - goto fail; - } - - /* Check the remaining pages in the new GDT. */ - for ( i = 1; i < nr_pages; i++ ) + /* Check the pages in the new GDT. */ + for ( i = 0; i < nr_pages; i++ ) if ( ((pfn = frames[i]) >= max_page) || !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) ) goto fail; - /* Copy reserved GDT entries to the new GDT. */ - vgdt = map_domain_mem(frames[0] << PAGE_SHIFT); - memcpy(vgdt + FIRST_RESERVED_GDT_ENTRY, - gdt_table + FIRST_RESERVED_GDT_ENTRY, - NR_RESERVED_GDT_ENTRIES*8); - unmap_domain_mem(vgdt); - /* Tear down the old GDT. */ destroy_gdt(ed); /* Install the new GDT. */ + ed->arch.guest_context.gdt_ents = entries; for ( i = 0; i < nr_pages; i++ ) + { + ed->arch.guest_context.gdt_frames[i] = frames[i]; ed->arch.perdomain_ptes[i] = l1e_create_pfn(frames[i], __PAGE_HYPERVISOR); - - SET_GDT_ADDRESS(ed, GDT_VIRT_START(ed)); - SET_GDT_ENTRIES(ed, entries); + } return 0; @@ -2325,19 +2302,13 @@ long do_set_gdt(unsigned long *frame_list, unsigned int entries) unsigned long frames[16]; long ret; - if ( (entries <= LAST_RESERVED_GDT_ENTRY) || (entries > 8192) ) - return -EINVAL; - if ( copy_from_user(frames, frame_list, nr_pages * sizeof(unsigned long)) ) return -EFAULT; LOCK_BIGLOCK(current->domain); if ( (ret = set_gdt(current, frames, entries)) == 0 ) - { local_flush_tlb(); - __asm__ __volatile__ ("lgdt %0" : "=m" (*current->arch.gdt)); - } UNLOCK_BIGLOCK(current->domain); @@ -2352,7 +2323,6 @@ long do_update_descriptor(unsigned long pa, u64 desc) unsigned long mfn; struct desc_struct *gdt_pent, d; struct pfn_info *page; - struct exec_domain *ed; long ret = -EINVAL; *(u64 *)&d = desc; @@ -2379,13 +2349,6 @@ long do_update_descriptor(unsigned long pa, u64 desc) switch ( page->u.inuse.type_info & PGT_type_mask ) { case PGT_gdt_page: - /* Disallow updates of Xen-reserved descriptors in the current GDT. */ - for_each_exec_domain(dom, ed) { - if ( (l1e_get_pfn(ed->arch.perdomain_ptes[0]) == mfn) && - (((pa&(PAGE_SIZE-1))>>3) >= FIRST_RESERVED_GDT_ENTRY) && - (((pa&(PAGE_SIZE-1))>>3) <= LAST_RESERVED_GDT_ENTRY) ) - goto out; - } if ( unlikely(!get_page_type(page, PGT_gdt_page)) ) goto out; break; diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 49eb0d275b..05721b5d2c 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -295,14 +295,15 @@ void __init cpu_init(void) { int nr = smp_processor_id(); struct tss_struct *t = &init_tss[nr]; + char gdt_load[10]; if ( test_and_set_bit(nr, &cpu_initialized) ) panic("CPU#%d already initialized!!!\n", nr); printk("Initializing CPU#%d\n", nr); - SET_GDT_ENTRIES(current, DEFAULT_GDT_ENTRIES); - SET_GDT_ADDRESS(current, DEFAULT_GDT_ADDRESS); - __asm__ __volatile__ ( "lgdt %0" : "=m" (*current->arch.gdt) ); + *(unsigned short *)(&gdt_load[0]) = LAST_RESERVED_GDT_BYTE; + *(unsigned long *)(&gdt_load[2]) = GDT_VIRT_START(current); + __asm__ __volatile__ ( "lgdt %0" : "=m" (gdt_load) ); /* No nested task. */ __asm__ __volatile__ ( "pushf ; andw $0xbfff,(%"__OP"sp) ; popf" ); @@ -391,10 +392,19 @@ static void __init start_of_day(void) sort_exception_tables(); arch_do_createdomain(current); - - identify_cpu(&boot_cpu_data); /* get CPU type info */ - if ( cpu_has_fxsr ) set_in_cr4(X86_CR4_OSFXSR); - if ( cpu_has_xmm ) set_in_cr4(X86_CR4_OSXMMEXCPT); + + /* Map default GDT into their final position in the idle page table. */ + map_pages( + idle_pg_table, + GDT_VIRT_START(current) + FIRST_RESERVED_GDT_BYTE, + virt_to_phys(gdt_table), PAGE_SIZE, __PAGE_HYPERVISOR); + + /* Process CPU type information. */ + identify_cpu(&boot_cpu_data); + if ( cpu_has_fxsr ) + set_in_cr4(X86_CR4_OSFXSR); + if ( cpu_has_xmm ) + set_in_cr4(X86_CR4_OSXMMEXCPT); find_smp_config(); diff --git a/xen/arch/x86/trampoline.S b/xen/arch/x86/trampoline.S index f72afac0ce..44baea0bbb 100644 --- a/xen/arch/x86/trampoline.S +++ b/xen/arch/x86/trampoline.S @@ -17,6 +17,7 @@ #include #include +#include #include #ifdef CONFIG_SMP @@ -54,11 +55,11 @@ idt_48: .word 0, 0 # idt base = 0L gdt_48: - .word (LAST_RESERVED_GDT_ENTRY*8)+7 + .word LAST_RESERVED_GDT_BYTE #ifdef __i386__ - .long gdt_table-__PAGE_OFFSET + .long gdt_table - FIRST_RESERVED_GDT_BYTE - __PAGE_OFFSET #else - .long 0x100200 # gdt_table + .long 0x101000 - FIRST_RESERVED_GDT_BYTE #endif ENTRY(trampoline_end) diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 8851e30b87..da39f5c966 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -70,25 +70,29 @@ string_param("nmi", opt_nmi); /* Master table, used by all CPUs on x86/64, and by CPU0 on x86/32.*/ idt_entry_t idt_table[IDT_ENTRIES]; -asmlinkage void divide_error(void); -asmlinkage void debug(void); +#define DECLARE_TRAP_HANDLER(_name) \ +asmlinkage void _name(void); \ +asmlinkage int do_ ## _name(struct cpu_user_regs *regs) + asmlinkage void nmi(void); -asmlinkage void int3(void); -asmlinkage void overflow(void); -asmlinkage void bounds(void); -asmlinkage void invalid_op(void); -asmlinkage void device_not_available(void); -asmlinkage void coprocessor_segment_overrun(void); -asmlinkage void invalid_TSS(void); -asmlinkage void segment_not_present(void); -asmlinkage void stack_segment(void); -asmlinkage void general_protection(void); -asmlinkage void page_fault(void); -asmlinkage void coprocessor_error(void); -asmlinkage void simd_coprocessor_error(void); -asmlinkage void alignment_check(void); -asmlinkage void spurious_interrupt_bug(void); -asmlinkage void machine_check(void); +DECLARE_TRAP_HANDLER(divide_error); +DECLARE_TRAP_HANDLER(debug); +DECLARE_TRAP_HANDLER(int3); +DECLARE_TRAP_HANDLER(overflow); +DECLARE_TRAP_HANDLER(bounds); +DECLARE_TRAP_HANDLER(invalid_op); +DECLARE_TRAP_HANDLER(device_not_available); +DECLARE_TRAP_HANDLER(coprocessor_segment_overrun); +DECLARE_TRAP_HANDLER(invalid_TSS); +DECLARE_TRAP_HANDLER(segment_not_present); +DECLARE_TRAP_HANDLER(stack_segment); +DECLARE_TRAP_HANDLER(general_protection); +DECLARE_TRAP_HANDLER(page_fault); +DECLARE_TRAP_HANDLER(coprocessor_error); +DECLARE_TRAP_HANDLER(simd_coprocessor_error); +DECLARE_TRAP_HANDLER(alignment_check); +DECLARE_TRAP_HANDLER(spurious_interrupt_bug); +DECLARE_TRAP_HANDLER(machine_check); static int debug_stack_lines = 20; integer_param("debug_stack_lines", debug_stack_lines); @@ -327,9 +331,10 @@ asmlinkage int do_int3(struct cpu_user_regs *regs) return 0; } -asmlinkage void do_machine_check(struct cpu_user_regs *regs) +asmlinkage int do_machine_check(struct cpu_user_regs *regs) { fatal_trap(TRAP_machine_check, regs); + return 0; } void propagate_page_fault(unsigned long addr, u16 error_code) @@ -350,12 +355,57 @@ void propagate_page_fault(unsigned long addr, u16 error_code) ed->arch.guest_cr2 = addr; } +static int handle_perdomain_mapping_fault( + unsigned long offset, struct cpu_user_regs *regs) +{ + extern int map_ldt_shadow_page(unsigned int); + + struct exec_domain *ed = current; + struct domain *d = ed->domain; + int ret; + + /* Which vcpu's area did we fault in, and is it in the ldt sub-area? */ + unsigned int is_ldt_area = (offset >> (PDPT_VCPU_VA_SHIFT-1)) & 1; + unsigned int vcpu_area = (offset >> PDPT_VCPU_VA_SHIFT); + + /* Should never fault in another vcpu's area. */ + BUG_ON(vcpu_area != current->vcpu_id); + + /* Byte offset within the gdt/ldt sub-area. */ + offset &= (1UL << (PDPT_VCPU_VA_SHIFT-1)) - 1UL; + + if ( likely(is_ldt_area) ) + { + /* LDT fault: Copy a mapping from the guest's LDT, if it is valid. */ + LOCK_BIGLOCK(d); + ret = map_ldt_shadow_page(offset >> PAGE_SHIFT); + UNLOCK_BIGLOCK(d); + + if ( unlikely(ret == 0) ) + { + /* In hypervisor mode? Leave it to the #PF handler to fix up. */ + if ( !GUEST_MODE(regs) ) + return 0; + /* In guest mode? Propagate #PF to guest, with adjusted %cr2. */ + propagate_page_fault( + ed->arch.guest_context.ldt_base + offset, regs->error_code); + } + } + else + { + /* GDT fault: handle the fault as #GP(selector). */ + regs->error_code = (u16)offset & ~7; + (void)do_general_protection(regs); + } + + return EXCRET_fault_fixed; +} + asmlinkage int do_page_fault(struct cpu_user_regs *regs) { - unsigned long off, addr, fixup; + unsigned long addr, fixup; struct exec_domain *ed = current; struct domain *d = ed->domain; - int ret; __asm__ __volatile__ ("mov %%cr2,%0" : "=r" (addr) : ); @@ -390,27 +440,12 @@ asmlinkage int do_page_fault(struct cpu_user_regs *regs) ((addr < HYPERVISOR_VIRT_START) || (shadow_mode_external(d) && GUEST_CONTEXT(ed, regs))) && shadow_fault(addr, regs) ) - { return EXCRET_fault_fixed; - } - if ( unlikely(addr >= LDT_VIRT_START(ed)) && - (addr < (LDT_VIRT_START(ed) + - (ed->arch.guest_context.ldt_ents*LDT_ENTRY_SIZE))) ) - { - /* - * Copy a mapping from the guest's LDT, if it is valid. Otherwise we - * send the fault up to the guest OS to be handled. - */ - extern int map_ldt_shadow_page(unsigned int); - LOCK_BIGLOCK(d); - off = addr - LDT_VIRT_START(ed); - addr = ed->arch.guest_context.ldt_base + off; - ret = map_ldt_shadow_page(off >> PAGE_SHIFT); - UNLOCK_BIGLOCK(d); - if ( likely(ret) ) - return EXCRET_fault_fixed; /* successfully copied the mapping */ - } + if ( unlikely(addr >= PERDOMAIN_VIRT_START) && + unlikely(addr < PERDOMAIN_VIRT_END) && + handle_perdomain_mapping_fault(addr - PERDOMAIN_VIRT_START, regs) ) + return EXCRET_fault_fixed; if ( !GUEST_MODE(regs) ) goto xen_fault; @@ -1097,7 +1132,7 @@ void set_task_gate(unsigned int n, unsigned int sel) void set_tss_desc(unsigned int n, void *addr) { _set_tssldt_desc( - gdt_table + __TSS(n), + gdt_table + __TSS(n) - FIRST_RESERVED_GDT_ENTRY, (unsigned long)addr, offsetof(struct tss_struct, __cacheline_filler) - 1, 9); diff --git a/xen/arch/x86/x86_32/seg_fixup.c b/xen/arch/x86/x86_32/seg_fixup.c index 484ff64fd4..f0d7f8543e 100644 --- a/xen/arch/x86/x86_32/seg_fixup.c +++ b/xen/arch/x86/x86_32/seg_fixup.c @@ -120,8 +120,8 @@ int get_baselimit(u16 seg, unsigned long *base, unsigned long *limit) } else /* gdt */ { - table = (unsigned long *)GET_GDT_ADDRESS(d); - if ( idx >= GET_GDT_ENTRIES(d) ) + table = (unsigned long *)GDT_VIRT_START(d); + if ( idx >= d->arch.guest_context.gdt_ents ) goto fail; } @@ -184,17 +184,17 @@ int fixup_seg(u16 seg, unsigned long offset) if ( idx >= d->arch.guest_context.ldt_ents ) { DPRINTK("Segment %04x out of LDT range (%ld)\n", - seg, d->arch.ldt_ents); + seg, d->arch.guest_context.ldt_ents); goto fail; } } else /* gdt */ { - table = (unsigned long *)GET_GDT_ADDRESS(d); - if ( idx >= GET_GDT_ENTRIES(d) ) + table = (unsigned long *)GDT_VIRT_START(d); + if ( idx >= d->arch.guest_context.gdt_ents ) { - DPRINTK("Segment %04x out of GDT range (%d)\n", - seg, GET_GDT_ENTRIES(d)); + DPRINTK("Segment %04x out of GDT range (%ld)\n", + seg, d->arch.guest_context.gdt_ents); goto fail; } } diff --git a/xen/arch/x86/x86_32/traps.c b/xen/arch/x86/x86_32/traps.c index a75badbad7..0e391a4ea6 100644 --- a/xen/arch/x86/x86_32/traps.c +++ b/xen/arch/x86/x86_32/traps.c @@ -178,8 +178,9 @@ void __init percpu_traps_init(void) tss->eip = (unsigned long)do_double_fault; tss->eflags = 2; tss->bitmap = IOBMP_INVALID_OFFSET; - _set_tssldt_desc(gdt_table+__DOUBLEFAULT_TSS_ENTRY, - (unsigned long)tss, 235, 9); + _set_tssldt_desc( + gdt_table + __DOUBLEFAULT_TSS_ENTRY - FIRST_RESERVED_GDT_ENTRY, + (unsigned long)tss, 235, 9); set_task_gate(TRAP_double_fault, __DOUBLEFAULT_TSS_ENTRY<<3); } diff --git a/xen/include/asm-x86/config.h b/xen/include/asm-x86/config.h index d98a57e5a2..5e4f6196ec 100644 --- a/xen/include/asm-x86/config.h +++ b/xen/include/asm-x86/config.h @@ -27,10 +27,6 @@ #define OPT_CONSOLE_STR "com1,vga" -/* - * If you increase this value, please update NR_RESERVED_GDT_ENTRIES - * in include/public/arch-x86_xx.h - */ #define NR_CPUS 32 /* Linkage for x86 */ @@ -160,18 +156,18 @@ extern unsigned long _end; /* standard ELF symbol */ #define PGT_base_page_table PGT_l4_page_table -#define __HYPERVISOR_CS64 0x0810 -#define __HYPERVISOR_CS32 0x0808 +#define __HYPERVISOR_CS64 0xe010 +#define __HYPERVISOR_CS32 0xe008 #define __HYPERVISOR_CS __HYPERVISOR_CS64 #define __HYPERVISOR_DS64 0x0000 -#define __HYPERVISOR_DS32 0x0818 +#define __HYPERVISOR_DS32 0xe018 #define __HYPERVISOR_DS __HYPERVISOR_DS64 -#define __GUEST_CS64 0x0833 -#define __GUEST_CS32 0x0823 +#define __GUEST_CS64 0xe033 +#define __GUEST_CS32 0xe023 #define __GUEST_CS __GUEST_CS64 #define __GUEST_DS 0x0000 -#define __GUEST_SS 0x082b +#define __GUEST_SS 0xe02b /* For generic assembly code: use macros to define operation/operand sizes. */ #define __OS "q" /* Operation Suffix */ @@ -260,8 +256,8 @@ extern unsigned long _end; /* standard ELF symbol */ #define PGT_base_page_table PGT_l2_page_table -#define __HYPERVISOR_CS 0x0808 -#define __HYPERVISOR_DS 0x0810 +#define __HYPERVISOR_CS 0xe008 +#define __HYPERVISOR_DS 0xe010 /* For generic assembly code: use macros to define operation/operand sizes. */ #define __OS "l" /* Operation Suffix */ @@ -275,10 +271,10 @@ extern unsigned long _end; /* standard ELF symbol */ extern unsigned long xenheap_phys_end; /* user-configurable */ #endif -#define GDT_VIRT_START(ed) (PERDOMAIN_VIRT_START + ((ed)->vcpu_id << PDPT_VCPU_VA_SHIFT)) -#define GDT_VIRT_END(ed) (GDT_VIRT_START(ed) + (64*1024)) -#define LDT_VIRT_START(ed) (PERDOMAIN_VIRT_START + (64*1024) + ((ed)->vcpu_id << PDPT_VCPU_VA_SHIFT)) -#define LDT_VIRT_END(ed) (LDT_VIRT_START(ed) + (64*1024)) +#define GDT_VIRT_START(ed) \ + (PERDOMAIN_VIRT_START + ((ed)->vcpu_id << PDPT_VCPU_VA_SHIFT)) +#define LDT_VIRT_START(ed) \ + (GDT_VIRT_START(ed) + (64*1024)) #define PDPT_VCPU_SHIFT 5 #define PDPT_VCPU_VA_SHIFT (PDPT_VCPU_SHIFT + PAGE_SHIFT) diff --git a/xen/include/asm-x86/desc.h b/xen/include/asm-x86/desc.h index a05bb752e9..6d45d0cb2b 100644 --- a/xen/include/asm-x86/desc.h +++ b/xen/include/asm-x86/desc.h @@ -1,6 +1,20 @@ #ifndef __ARCH_DESC_H #define __ARCH_DESC_H -#ifndef __ASSEMBLY__ + +/* + * Xen reserves a memory page of GDT entries. + * No guest GDT entries exist beyond the Xen reserved area. + */ +#define NR_RESERVED_GDT_PAGES 1 +#define NR_RESERVED_GDT_BYTES (NR_RESERVED_GDT_PAGES * PAGE_SIZE) +#define NR_RESERVED_GDT_ENTRIES (NR_RESERVED_GDT_BYTES / 8) + +#define LAST_RESERVED_GDT_PAGE \ + (FIRST_RESERVED_GDT_PAGE + NR_RESERVED_GDT_PAGES - 1) +#define LAST_RESERVED_GDT_BYTE \ + (FIRST_RESERVED_GDT_BYTE + NR_RESERVED_GDT_BYTES - 1) +#define LAST_RESERVED_GDT_ENTRY \ + (FIRST_RESERVED_GDT_ENTRY + NR_RESERVED_GDT_ENTRIES - 1) #define LDT_ENTRY_SIZE 8 @@ -19,9 +33,7 @@ * is ignored when the gate is accessed. */ #define VALID_SEL(_s) \ - (((((_s)>>3) < FIRST_RESERVED_GDT_ENTRY) || \ - (((_s)>>3) > LAST_RESERVED_GDT_ENTRY) || \ - ((_s)&4)) && \ + (((((_s)>>3) < FIRST_RESERVED_GDT_ENTRY) || ((_s)&4)) && \ (((_s)&3) == GUEST_KERNEL_RPL)) #define VALID_CODESEL(_s) ((_s) == FLAT_KERNEL_CS || VALID_SEL(_s)) @@ -36,6 +48,8 @@ #define _SEGMENT_DB ( 1<<22) /* 16- or 32-bit segment */ #define _SEGMENT_G ( 1<<23) /* Granularity */ +#ifndef __ASSEMBLY__ + struct desc_struct { u32 a, b; }; @@ -133,4 +147,5 @@ extern void set_task_gate(unsigned int n, unsigned int sel); extern void set_tss_desc(unsigned int n, void *addr); #endif /* !__ASSEMBLY__ */ + #endif /* __ARCH_DESC_H */ diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index 79eda33a07..98da7e017a 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -117,8 +117,6 @@ struct arch_exec_domain /* Current LDT details. */ unsigned long shadow_ldt_mapcnt; - /* Next entry is passed to LGDT on domain switch. */ - char gdt[10]; /* NB. 10 bytes needed for x86_64. Use 6 bytes for x86_32. */ } __cacheline_aligned; #define IDLE0_ARCH_EXEC_DOMAIN \ diff --git a/xen/include/asm-x86/ldt.h b/xen/include/asm-x86/ldt.h index 63fa8db5d8..33de175165 100644 --- a/xen/include/asm-x86/ldt.h +++ b/xen/include/asm-x86/ldt.h @@ -17,7 +17,7 @@ static inline void load_LDT(struct exec_domain *ed) else { cpu = smp_processor_id(); - desc = (struct desc_struct *)GET_GDT_ADDRESS(ed) + __LDT(cpu); + desc = gdt_table + __LDT(cpu) - FIRST_RESERVED_GDT_ENTRY; desc->a = ((LDT_VIRT_START(ed)&0xffff)<<16) | (ents*8-1); desc->b = (LDT_VIRT_START(ed)&(0xff<<24)) | 0x8200 | ((LDT_VIRT_START(ed)&0xff0000)>>16); diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h index cf4e88bc6d..bbab724e48 100644 --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -274,9 +274,6 @@ static inline unsigned long phys_to_machine_mapping(unsigned long pfn) } #define set_machinetophys(_mfn, _pfn) machine_to_phys_mapping[(_mfn)] = (_pfn) -#define DEFAULT_GDT_ENTRIES (LAST_RESERVED_GDT_ENTRY+1) -#define DEFAULT_GDT_ADDRESS ((unsigned long)gdt_table) - #ifdef MEMORY_GUARD void *memguard_init(void *heap_start); void memguard_guard_stack(void *p); diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h index 9ccfcf3f3a..907c820c12 100644 --- a/xen/include/asm-x86/processor.h +++ b/xen/include/asm-x86/processor.h @@ -392,15 +392,6 @@ extern int gpf_emulate_4gb(struct cpu_user_regs *regs); extern void write_ptbase(struct exec_domain *ed); -#define SET_GDT_ENTRIES(_p, _e) \ - ((*(u16 *)((_p)->arch.gdt + 0)) = (((_e)<<3)-1)) -#define SET_GDT_ADDRESS(_p, _a) \ - ((*(unsigned long *)((_p)->arch.gdt + 2)) = (_a)) -#define GET_GDT_ENTRIES(_p) \ - (((*(u16 *)((_p)->arch.gdt + 0))+1)>>3) -#define GET_GDT_ADDRESS(_p) \ - (*(unsigned long *)((_p)->arch.gdt + 2)) - void destroy_gdt(struct exec_domain *d); long set_gdt(struct exec_domain *d, unsigned long *frames, diff --git a/xen/include/asm-x86/x86_64/ldt.h b/xen/include/asm-x86/x86_64/ldt.h deleted file mode 100644 index 1e09163867..0000000000 --- a/xen/include/asm-x86/x86_64/ldt.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef __ARCH_LDT_H -#define __ARCH_LDT_H - -#ifndef __ASSEMBLY__ - -static inline void load_LDT(struct domain *p) -{ - unsigned long ents; - - if ( (ents = p->mm.ldt_ents) == 0 ) - { - __asm__ __volatile__ ( "lldt %w0" : : "r" (0) ); - } - else - { - unsigned int cpu; - struct ldttss_desc *desc; - - cpu = smp_processor_id(); - desc = (struct ldttss_desc *)((char *)GET_GDT_ADDRESS(p) + __CPU_DESC_INDEX(cpu, ldt)); - desc->limit0 = ents*8-1; - desc->base0 = LDT_VIRT_START&0xffff; - desc->base1 = (LDT_VIRT_START&0xff0000)>>16; - desc->type = DESC_LDT; - desc->dpl = 0; - desc->p = 1; - desc->limit1 = 0; - desc->zero0 = 0; - desc->g = 0; - desc->base2 = (LDT_VIRT_START&0xff000000)>>24; - desc->base3 = LDT_VIRT_START>>32; - desc->zero1 = 0; - __load_LDT(cpu); - } -} - -#endif /* !__ASSEMBLY__ */ - -#endif diff --git a/xen/include/public/arch-x86_32.h b/xen/include/public/arch-x86_32.h index 35d97e2b3d..6ebfd11399 100644 --- a/xen/include/public/arch-x86_32.h +++ b/xen/include/public/arch-x86_32.h @@ -31,31 +31,23 @@ * A number of GDT entries are reserved by Xen. These are not situated at the * start of the GDT because some stupid OSes export hard-coded selector values * in their ABI. These hard-coded values are always near the start of the GDT, - * so Xen places itself out of the way. - * - * NR_RESERVED_GDT_ENTRIES is (8 + 2 * NR_CPUS) Please update this value if - * you increase NR_CPUS or add another GDT entry to gdt_table in x86_32.S - * - * NB. The reserved range is inclusive (that is, both FIRST_RESERVED_GDT_ENTRY - * and LAST_RESERVED_GDT_ENTRY are reserved). + * so Xen places itself out of the way, at the far end of the GDT. */ -#define NR_RESERVED_GDT_ENTRIES 72 -#define FIRST_RESERVED_GDT_ENTRY 256 -#define LAST_RESERVED_GDT_ENTRY \ - (FIRST_RESERVED_GDT_ENTRY + NR_RESERVED_GDT_ENTRIES - 1) - +#define FIRST_RESERVED_GDT_PAGE 14 +#define FIRST_RESERVED_GDT_BYTE (FIRST_RESERVED_GDT_PAGE * 4096) +#define FIRST_RESERVED_GDT_ENTRY (FIRST_RESERVED_GDT_BYTE / 8) /* * These flat segments are in the Xen-private section of every GDT. Since these * are also present in the initial GDT, many OSes will be able to avoid * installing their own GDT. */ -#define FLAT_RING1_CS 0x0819 /* GDT index 259 */ -#define FLAT_RING1_DS 0x0821 /* GDT index 260 */ -#define FLAT_RING1_SS 0x0821 /* GDT index 260 */ -#define FLAT_RING3_CS 0x082b /* GDT index 261 */ -#define FLAT_RING3_DS 0x0833 /* GDT index 262 */ -#define FLAT_RING3_SS 0x0833 /* GDT index 262 */ +#define FLAT_RING1_CS 0xe019 /* GDT index 259 */ +#define FLAT_RING1_DS 0xe021 /* GDT index 260 */ +#define FLAT_RING1_SS 0xe021 /* GDT index 260 */ +#define FLAT_RING3_CS 0xe02b /* GDT index 261 */ +#define FLAT_RING3_DS 0xe033 /* GDT index 262 */ +#define FLAT_RING3_SS 0xe033 /* GDT index 262 */ #define FLAT_KERNEL_CS FLAT_RING1_CS #define FLAT_KERNEL_DS FLAT_RING1_DS diff --git a/xen/include/public/arch-x86_64.h b/xen/include/public/arch-x86_64.h index 8e821688f7..c1a6699285 100644 --- a/xen/include/public/arch-x86_64.h +++ b/xen/include/public/arch-x86_64.h @@ -25,18 +25,11 @@ * A number of GDT entries are reserved by Xen. These are not situated at the * start of the GDT because some stupid OSes export hard-coded selector values * in their ABI. These hard-coded values are always near the start of the GDT, - * so Xen places itself out of the way. - * - * NR_RESERVED_GDT_ENTRIES is (8 + 4 * NR_CPUS) Please update this value if - * you increase NR_CPUS or add another GDT entry to gdt_table in boot/x86_64.S - * - * NB. The reserved range is inclusive (that is, both FIRST_RESERVED_GDT_ENTRY - * and LAST_RESERVED_GDT_ENTRY are reserved). + * so Xen places itself out of the way, at the far end of the GDT. */ -#define NR_RESERVED_GDT_ENTRIES 136 -#define FIRST_RESERVED_GDT_ENTRY 256 -#define LAST_RESERVED_GDT_ENTRY \ - (FIRST_RESERVED_GDT_ENTRY + NR_RESERVED_GDT_ENTRIES - 1) +#define FIRST_RESERVED_GDT_PAGE 14 +#define FIRST_RESERVED_GDT_BYTE (FIRST_RESERVED_GDT_PAGE * 4096) +#define FIRST_RESERVED_GDT_ENTRY (FIRST_RESERVED_GDT_BYTE / 8) /* * 64-bit segment selectors @@ -45,12 +38,12 @@ * installing their own GDT. */ -#define FLAT_RING3_CS32 0x0823 /* GDT index 260 */ -#define FLAT_RING3_CS64 0x0833 /* GDT index 261 */ -#define FLAT_RING3_DS32 0x082b /* GDT index 262 */ +#define FLAT_RING3_CS32 0xe023 /* GDT index 260 */ +#define FLAT_RING3_CS64 0xe033 /* GDT index 261 */ +#define FLAT_RING3_DS32 0xe02b /* GDT index 262 */ #define FLAT_RING3_DS64 0x0000 /* NULL selector */ -#define FLAT_RING3_SS32 0x082b /* GDT index 262 */ -#define FLAT_RING3_SS64 0x082b /* GDT index 262 */ +#define FLAT_RING3_SS32 0xe02b /* GDT index 262 */ +#define FLAT_RING3_SS64 0xe02b /* GDT index 262 */ #define FLAT_KERNEL_DS64 FLAT_RING3_DS64 #define FLAT_KERNEL_DS32 FLAT_RING3_DS32 -- 2.30.2